package io.gitee.caoxiaoyu97.log.sensitive.pattern;

import io.gitee.caoxiaoyu97.log.sensitive.util.KeywordTypeEnum;
import io.gitee.caoxiaoyu97.log.sensitive.util.SensitiveInfoUtils;

import java.util.AbstractMap;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/*********************************************************
 * 文件名称：SensitiveDataConverter.java
 * 系统名称：bfts
 * 模块名称：com.hundsun.tbsp.bfts.other.base.log.sensitive.pattern
 * 功能说明：
 * 开发人员 @author：caoxy31978
 * 开发时间 @date：2025/9/26 15:37
 * 修改记录：程序版本  修改日期  修改人员  修改单号  修改说明
 *********************************************************/
public class SensitiveDataConverter {
    private static volatile SensitiveDataConverter instance;
    Map<String, BaseConverter> converters = new LinkedHashMap<>();
    boolean performeraceFirst = true;

    private SensitiveDataConverter(List<String> options){

        //如果存在参数选项，则提取
        if (options != null && options.size() >= 3) {
            String converterCanRun = String.valueOf(options.get(0));
            Integer maxLength = Integer.valueOf(options.get(1));
            performeraceFirst = ((options.get(2) != null) && !options.get(2).equalsIgnoreCase("false"));
            Map<String,String> keywordMap = new HashMap<>();

            if (options.size() > 3){
                List<String> strings = options.subList(3, options.size());
                Map<String, String> collect = strings.stream()
                        .filter(s -> s != null && !s.trim().isEmpty())
                        .map(s -> s.split(":"))
                        .filter(s -> s.length == 2)
                        .filter(s -> KeywordTypeEnum.getMessageType(s[0]) != null)
                        .flatMap(parts -> {
                            String type = parts[0];
                            String[] values = parts[1].split(";");
                            return Arrays.stream(values)
                                    .map(String::trim)
                                    .filter(v -> !v.isEmpty())
                                    .map(v -> new AbstractMap.SimpleEntry<>(v, type));
                        })
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(existing, replacement) -> existing));
                keywordMap.putAll(collect);
            }

            converters.put("KeywordType", new KeywordConverter(converterCanRun,maxLength,keywordMap));
            converters.put("Xml",new XmlConverter(converterCanRun,maxLength,keywordMap));
            converters.put("RegExp", new RegExpConverter(converterCanRun,maxLength));
        }
    }
    public static SensitiveDataConverter init(List<String> options){
        if (instance == null){
            synchronized (SensitiveDataConverter.class){
                if (instance == null){
                    instance = new SensitiveDataConverter(options);
                }
            }
        }
        return instance;
    }
    public static SensitiveDataConverter getInstance(){
        return instance;
    }

    public String convert(String message){

        for(BaseConverter converter:converters.values())
        {
            try {
                if(converter.canConverter()) {
                    String lastMessage = message;
                    message = converter.convert(lastMessage);
                    if(!message.equals(lastMessage)) {
                        if(performeraceFirst)
                            break;
                    }
                }
            }catch(Exception e) {
            }
        }
        return message;
    }

    protected static String facade(String msg, String key){

        String result = msg;
        KeywordTypeEnum keywordTypeEnum = KeywordTypeEnum.getMessageType(key);
        if (keywordTypeEnum == null) {
            keywordTypeEnum = KeywordTypeEnum.OTHER;
        }
        switch (keywordTypeEnum){
            case TRUE_NAME:
                result = SensitiveInfoUtils.handleTrueName(msg);break;
            case ID_CARD_NO:
                result = SensitiveInfoUtils.handleIdCardNo(msg);break;
            case BANKCARD_NO:
                result = SensitiveInfoUtils.handleBankcardNo(msg);break;
            case PHONE_NO:
                result = SensitiveInfoUtils.handlePhoneNo(msg);break;
            default :
                result = SensitiveInfoUtils.handleOther(msg);break;
        }
        return result;
    }
}
